import random from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) from django_countries.fields import CountryField # from otree.db.models import ForeignKey # Uncomment for Slider Task (https://github.com/chkgk/slider_task) # from slider_task.models import BaseSlider, SliderPlayer # Uncomment for Slider Task (https://github.com/chkgk/slider_task) author = 'Julian Hackinger' doc = """ This experiment is designed to test whether subjects are equally prone to exhibit the house money effect, i.e. violate the assumption of fungibility. It therefore comprises of three parts. In part one, participants need to earn their endowment in a real effort task. In part two, participants make decisions on how to allocate their endowment. In part three, participants complete intelligence tests. There are four treatments with respect to part one. In the Random High Effort treatment (RHE) and the Random Low Effort treatment (RLE) participants are told that they would either need to work little or much in order to earn their endowment. They are then assigned correspondingly to work either little or much. In the High Effort treatment (HE) and the Low Effort treatment (LE) participants are told that they would need to work little in the Low Effort treatment or much in the High Effort treatment. They are then assigned correspondingly. """ def levenshtein(a, b): """Calculates the Levenshtein distance between a and b.""" n, m = len(a), len(b) if n > m: # Make sure n <= m, to use O(min(n,m)) space a, b = b, a n, m = m, n current = range(n + 1) for i in range(1, m + 1): previous, current = current, [i] + [0] * n for j in range(1, n + 1): add, delete = previous[j] + 1, current[j - 1] + 1 change = previous[j - 1] if a[j - 1] != b[i - 1]: change = change + 1 current[j] = min(add, delete, change) return current[n] def distance_and_ok(transcribed_text, reference_text, max_error_rate): error_threshold = len(reference_text) * max_error_rate distance = levenshtein(transcribed_text, reference_text) ok = distance <= error_threshold return distance, ok class Constants(BaseConstants): name_in_url = 'house_money_effect' players_per_group = 2 num_rounds = 2 # Slider Task num_sliders = 4 # Number of sliders slider_list_high = [] for i in range(1, num_sliders + 1): slider_list_high.append('slider_high' + str(i)) print(slider_list_high) slider_list_low = [] for i in range(1, num_sliders + 1): slider_list_low.append('slider_low' + str(i)) print(slider_list_low) #slider_columns = 3 # Uncomment for Slider Task (https://github.com/chkgk/slider_task) # Initial amount allocated to the player endowment = c(100) multiplier = 2 reference_texts = [ "Revealed preference", "Hex ton satoha egavecen. Loh ta receso minenes da linoyiy xese coreliet ocotine! Senuh asud tu bubo tixorut sola, bo ipacape le rorisin lesiku etutale saseriec niyacin ponim na. Ri arariye senayi esoced behin? Tefid oveve duk mosar rototo buc: Leseri binin nolelar sise etolegus ibosa farare. Desac eno titeda res vab no mes!", ] allowed_error_rates = [0, 0.03] class Subsession(BaseSubsession): pass # Uncomment for Slider Task (https://github.com/chkgk/slider_task) # def creating_session(self): # for p in self.get_players(): # p.prepare_sliders(num=20, min=0, max=4) class Group(BaseGroup): # Dictator game donation = models.CurrencyField( doc="""Amount dictator decided to give""", min=0, max=Constants.endowment, ) # Public goods game total_contribution = models.CurrencyField() individual_share = models.CurrencyField() def set_payoffs_public_goods_game(self): self.total_contribution = sum([p.contribution for p in self.get_players()]) self.individual_share = self.total_contribution * Constants.multiplier / Constants.players_per_group for p in self.get_players(): p.payoff_public_goods_game = (Constants.endowment - p.contribution) + self.individual_share def set_payoffs_beliefs(self): for p in self.get_players(): p.payoff_belief = max(100 - (p.belief - p.get_partner().contribution)**2,0) # class Player(SliderPlayer): # Uncomment for Slider Task (https://github.com/chkgk/slider_task) class Player(BasePlayer): # Roles def role(self): if self.id_in_group == 1: return 'dictator' else: return 'receiver' def get_partner(self): return self.get_others_in_group()[0] # Slider Task def random_min(): return random.randint(0, 40) def random_max(): return random.randint(60, 100) # Slider High Effort def random_initial_high(): return random.randint(*random.choice([(0, 40), (60, 100)])) # Insert_Sliders_High_Start slider_high1 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_high()) slider_high2 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_high()) slider_high3 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_high()) slider_high4 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_high()) # Insert_Sliders_High_End # Slider Low Effort def random_initial_low(): return random.randint(*random.choice([(50, 50), (50, 50), (0, 40), (60, 100)])) # Insert_Sliders_Low_Start slider_low1 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_low()) slider_low2 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_low()) slider_low3 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_low()) slider_low4 = models.IntegerField( min=random_min(), max=random_max(), widget=widgets.Slider(), initial=random_initial_low()) # Insert_Sliders_Low_End # Transcribe Task transcribed_text = models.LongStringField() levenshtein_distance = models.IntegerField() # Dictator Game payoff_dictator_game = models.CurrencyField() def set_payoffs_dictator_game(self): self.group.get_player_by_role('dictator').payoff_dictator_game = Constants.endowment - self.group.donation self.group.get_player_by_role('receiver').payoff_dictator_game = self.group.donation # Public Goods Game contribution = models.CurrencyField( min=0, max=Constants.endowment, doc="""The amount contributed by the player""", ) payoff_public_goods_game = models.CurrencyField() # Beliefs belief = models.IntegerField( label=''' "What do you think the other player will contribute?" ''' ) payoff_belief = models.CurrencyField() # CRT: Frederick - Cognitive Reflection and Decision Making - 2005 crt_bat = models.IntegerField( label=''' A bat and a ball cost 22 dollars in total. The bat costs 20 dollars more than the ball. How many dollars does the ball cost?''' ) # (correct answer = 1; intuitive answer = 2) crt_widget = models.IntegerField( label=''' "If it takes 5 machines 5 minutes to make 5 widgets, how many minutes would it take 100 machines to make 100 widgets?" ''' ) # (correct answer = 5; intuitive answer = 100) crt_lake = models.IntegerField( label=''' In a lake, there is a patch of lily pads. Every day, the patch doubles in size. If it takes 48 days for the patch to cover the entire lake, how many days would it take for the patch to cover half of the lake? ''' ) # (correct answer = 47; intuitive answer = 24) # CRT: Primi et al - The Development and Testing of a New Version of the Cognitive Reflection Test Applying Item Response Theory - 2015 crt_elves = models.IntegerField( label='''If three elves can wrap three toys in hour, how many elves are needed to wrap six toys in 2 hours?''' ) # (correct answer = 3 elves; intuitive answer = 6 elves) crt_marks = models.IntegerField( label='''Jerry received both the 15th highest and the 15th lowest mark in the class. How many students are there in the class?''' ) # (correct answer= 29 students; intuitive answer= 30 students) crt_medals = models.IntegerField( label='''In an athletics team, tall members are three times more likely to win a medal than short members. This year the team has won 60 medals so far. How many of these have been won by short athletes?''' ) # (correct answer = 15 medals; intuitive answer = 20 medals) # CRT: Toplak, West, Stanovich - Assessing miserly information processing: an expansion of the Cognitive Reflection Test - 2014 # CRT5 is the same as CRT5 in Primi et al crt_water = models.IntegerField( label='''If John can drink one barrel of water in 6 days, and Mary can drink one barrel of water in 12 days, how long would it take them to drink one barrel of water together?''' ) # (correct answer = 4 days; intuitive answer = 9) crt_pig = models.IntegerField( label='''A man buys a pig for $60, sells it for $70, buys it back for $80, and sells it finally for $90. How much has he made?''' ) # (correct answer = $20; intuitive answer = $10) crt_stocks = models.StringField( label='''Simon decided to invest $8,000 in the stock market one day early in 2008. Six months after he invested, on July 17, the stocks he had purchased were down 50%. Fortunately for Simon, from July 17 to October 17, the stocks he had purchased went up 75%. At this point, Simon has:''', choices=['broken even in the stock market', 'is ahead of where he began', 'has lost money'], widget=widgets.RadioSelectHorizontal ) # (correct answer = c, because the value at this point is $7,000; intuitive response = b) # CRT: Thomson, Oppenheimer - Investigating an alternate form of the cognitive reflection test - 2016 crt_race = models.IntegerField( label='''If you’re running a race and you pass the person in second place, what place are you in?''' ) # (correct answer: second; intuitive answer: first) crt_sheep = models.IntegerField( label='''A farmer had 15 sheep and all but 8 died. How many are left?''' ) # (correct answer: 8; intuitive answer: 7) crt_emily = models.StringField( label='''Emily’s father has three daughters. The first two are named April and May. What is the third daughter’s name?''', choices=['June', 'Emily', 'nobody knows'], widget=widgets.RadioSelectHorizontal ) # (correct answer: Emily; intuitive answer: June) crt_hole = models.IntegerField( label='''How many cubic feet of dirt are there in a hole that is 3’deep x 3’ wide x 3’ long?''' ) # (correct answer: none; intuitive answer: 27) crt_familiarity = models.StringField( choices=['1', '2', '3', '4', '5'], label='How familiar have you been (1=not at all, 5=very)?', widget=widgets.RadioSelectHorizontal ) payoff_crt_bat = models.CurrencyField() payoff_crt_widget = models.CurrencyField() payoff_crt_lake = models.CurrencyField() payoff_crt = models.CurrencyField() def set_crt_payoff(self): if self.crt_bat == 1: self.payoff_crt_bat = 1 else: self.payoff_crt_bat = 0 if self.crt_widget == 5: self.payoff_crt_widget = 1 else: self.payoff_crt_widget = 0 if self.crt_lake == 47: self.payoff_crt_lake = 1 else: self.payoff_crt_lake = 0 self.payoff_crt = 3*(self.payoff_crt_bat + self.payoff_crt_widget + self.payoff_crt_lake) # Survey age = models.IntegerField( label='What is your age?', min=13, max=125 ) gender = models.StringField( choices=['Male', 'Female', 'Other'], label='What is your gender?', widget=widgets.RadioSelect ) country = CountryField( verbose_name='What is your country of citizenship?', blank_label='(select country)' ) # https://github.com/SmileyChris/django-countries risk = models.StringField( choices=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'], label='Assess yourself: Are you more of a risk-taking person or do you think of yourself as a risk-avoider? Please tick a box on the scale below, 0 indicating “no tolerance for risk” and 10 indicating “very risk-seeking”. The values in between can help you more finely represent your image of yourself.', widget=widgets.RadioSelectHorizontal ) # Final payoff def set_payoff(self): self.payoff = self.payoff_dictator_game + self.payoff_public_goods_game + self.payoff_belief + self.payoff_crt # Uncomment for Slider Task (https://github.com/chkgk/slider_task) # class Slider(BaseSlider): # player = ForeignKey(Player)